<template>
  <div class="container">
    <el-row :gutter="10">
      <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="m-10">
        <el-card header="📷图片识别">
          <el-alert
            title="支持图片粘贴和图片上传，支持拖动上传"
            type="info"
            :closable="false"
          >
            <template #default>
              <div class="flex">
                <div>PC端复制图片后可以直接ctrl+v，移动端可以点击右侧按钮粘贴</div>
                <el-tooltip content="粘贴图片" placement="bottom">
                  <el-icon @click="pasteImage"><Document /></el-icon>
                </el-tooltip>
              </div>
            </template>
          </el-alert>
          <ImageUpload @uploadFile="uploadImage" />
          <CanvasComponent
            ref="canvasRef"
            :imageList="imageList"
            :isAutoChoose="isAutoChoose"
            @select="onSelect"
            @delImage="delImage"
          />
          <div class="flex-between">
            <div><span>识别后自动选中符合的数字</span><el-switch v-model="isAutoChoose" /></div>
            
            <div>
              <el-button type="warning" plain @click="removeAll">清空</el-button>
              <el-button type="primary" plain @click="recognize">识别</el-button>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="m-10">
        <el-card header="💰金币计算">
          <el-alert title="识别或手动输入数字后，系统会自动计算结果，回车创建新的输入框" type="info" :closable="false"/>
          <el-row :gutter="5">
            <el-col
              :xs="24"
              :sm="24"
              :md="12"
              :lg="12"
              :xl="12"
              v-for="(_item, index) in inputValue"
              :key="index"
              class="m-10"
            >
              <div class="input-box">
                <label class="input-label">序号{{ index + 1 }}:</label>
                <el-input
                  :ref="setInput"
                  v-model.number="inputValue[index]" 
                  @keypress.enter="() => nextInput(index)"
                  clearable
                />
                <el-icon v-if="index!== 0" class="btn-icon" size="20" color="red" @click="deleteInput(index)"><DeleteFilled /></el-icon>
                <div v-else class="placeholder"></div>
              </div>
            </el-col>
            <el-col
              :xs="24"
              :sm="24"
              :md="12"
              :lg="12"
              :xl="12"
              class="m-10 flex"
            >
              <el-icon class="btn-icon" size="20" color="#409eff" @click="addInput"><CirclePlusFilled /></el-icon>
            </el-col>
          </el-row>
          <el-divider />
          <div class="flex">
            <div class="lh-32">金币总和：{{ formatNumber(inputSum) }}</div>
            <el-tooltip content="复制" placement="bottom">
              <el-icon @click="copyToClipboard"><Document /></el-icon>
            </el-tooltip>
          </div>
          <el-row :gutter="5">
            <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
              <div class="input-box">
                <label class="input-label">金币比例：</label>
                <el-input v-model.number="coinRatio" />
              </div>
            </el-col>
            <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"><div class="lh-32">人民币：{{ rmb }}￥</div></el-col>
          </el-row>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import ImageUpload from '@/components/upload.vue';
import CanvasComponent from '@/components/canvas.vue';
import { computed, nextTick, ref } from 'vue';
import { ElLoading, ElMessage } from 'element-plus';
import { paddleOCRApi } from '@/api';
import { formatNumber, generateUUID } from '@/utils';

// 粘贴图片方法
const clipboardImage = (file: any) => {
  const reader = new FileReader();
  reader.onload = (e: any) => {
    const base64 = e.target.result;
    const img = new Image();
    img.onload = () => {
      const width = img.width;
      const height = img.height;
      imageList.value.push({
        id: generateUUID(),
        url: base64,
        recognizeResult: null,
        width,
        height,
      });
      ElMessage.success("图片上传成功🌻");
    }
    img.src = base64;
  }
  reader.readAsDataURL(file);
}

// 绑定粘贴事件
document.addEventListener('paste', (event: ClipboardEvent) => {
  event.preventDefault();
  const items = event.clipboardData?.items;
  if (!items || items.length === 0) {
    ElMessage.warning("未发现图片，请先复制图片后再粘贴");
    return;
  }
  let hasImage = false;
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (item.type.indexOf('image') === -1) break;
    const file = item.getAsFile();
    if (file) {
      clipboardImage(file);
      hasImage = true;
    }
  }
  if (!hasImage) ElMessage.warning("未发现图片，请先复制图片后再粘贴");
});
// 粘贴图片
const pasteImage = async () => {
  try {
    const items = await navigator.clipboard.read();
    if (!items || items.length === 0) {
      ElMessage.warning("未发现图片，请先复制图片后再粘贴");
      return;
    }
    let hasImage = false;
    for (let i = 0; i < items.length; i++) {
      const item = items[i];
      const { types } = item;
      if (!types.includes('image/png') && !types.includes('image/jpeg')) break;
      const blob = await item.getType(types[0]);
      if (blob) {
        clipboardImage(blob);
        hasImage = true;
      }
    }
    if (!hasImage) ElMessage.warning("未发现图片，请先复制图片后再粘贴");
  } catch (error: any) {
    if(error.name === 'NotAllowedError') ElMessage.error('请先允许访问剪贴板');
  }
};
// 图片列表
const imageList = ref<any[]>([]);
// 上传图片
const uploadImage = (file: any) => {
  const img = new Image();
  img.onload = () => {
    const width = img.width;
    const height = img.height;
    imageList.value.push({
      id: generateUUID(),
      url: file,
      recognizeResult: null,
      width,
      height,
    });
  }
  img.src = file;
}
// 删除图片
const delImage = (id: string) => {
  imageList.value = imageList.value.filter(item => item.id!== id);
};
// 清空图片
const removeAll = () => {
  imageList.value = [];
  inputValue.value = ['', ''];
  canvasRef.value.clearAll();
};

// canvas组件
const canvasRef = ref<any>();

// 选择文本
const onSelect = (text: string, isSelected: boolean) => {
  // 从文本中提取出数字
  const numbers = text.match(/\d+/g);
  if (!numbers || numbers.length === 0) return
  const number = Number(numbers.join('')).toString();
  if(isSelected) {
    // 选中
    const nullIndex = inputValue.value.indexOf('');
    if (nullIndex!== -1) {
      inputValue.value[nullIndex] = number;
    } else {
      inputValue.value.push(number);
    }
  } else {
    // 取消选中
    const index = inputValue.value.indexOf(number);
    if (index === -1) return
    if(inputValue.value.length === 1) {
      inputValue.value[0] = '';
    } else {
      inputValue.value.splice(index, 1);
    }
  }
};
// 是否自动选择
const isAutoChoose = ref(true)
// 识别
const recognize = async () => {
  const loadingInstance = ElLoading.service({
    text: "正在识别...",
    background: "rgba(0,0,0,.2)"
  });
  try {
    const res: any = await Promise.all(imageList.value.map(file =>  paddleOCRApi({ image: file.url.split(',')[1] })));
    res.forEach((item: any, index: number) => {
      imageList.value[index].recognizeResult = item.data.result[0];
    });
  } catch (error) {
    console.log(error);
  } finally {
    loadingInstance.close();
  }
}

// 输入框值
const inputValue = ref(['', '']);
// 已经删除的输入框实例
let deletedInputRef: any[] = [];
// 输入框实例
const inputRef = ref<HTMLInputElement[]>([]);
const setInput = (el: HTMLInputElement) => {
  if (!el || inputRef.value.includes(el) || deletedInputRef.includes(el)) return
  inputRef.value.push(el);
};
// 输入框回车事件
const nextInput = (index: number) => {
  if (index === inputValue.value.length - 1) {
    inputValue.value.push('');
  }
  nextTick(() => {
    inputRef.value[index + 1].focus();
  })
}
// 添加输入框
const addInput = () => {
  inputValue.value.push('');
  nextTick(() => {
    inputRef.value[inputValue.value.length - 1].focus();
  })
}
// 删除输入框
const deleteInput = (index: number) => {
  inputValue.value.splice(index, 1);
  deletedInputRef.push(...inputRef.value.splice(index, 1));
}

// 金币总和
const inputSum = computed(() => inputValue.value.reduce((acc: number, cur: any) => {
  if (isNaN(cur)) {
    return acc;
  }
  return acc + Number(cur);
}, 0))
// 金币比例
const coinRatio = ref(10000);
// 计算人民币
const rmb = computed(() => (coinRatio.value ? (inputSum.value / coinRatio.value) : 0).toFixed(2));
// 复制到剪贴板
const copyToClipboard = async () => {
  try {
    await navigator.clipboard.writeText(inputSum.value.toString());
    ElMessage.success("金币总和已复制到剪贴板🌻")
  } catch (error) {
    console.log(error);
    
    ElMessage.warning("复制失败🌻");
  }
}
</script>

<style lang="less" scoped>
.container {
  box-sizing: border-box;
  background-color: #fafafa;
  min-height: 100vh;
  margin: 0 5px;
  padding: 10px;
  .input-label {
    width: 80px;
  }
  .input-box {
    display: flex;
    align-items: center;
    + .input-box {
      margin-top: 10px;
    }
    .el-input {
      flex: 1;
    }
  }
  .btn-icon {
    cursor: pointer;
    margin-left: 5px;
  }
  .placeholder {
    width: 25px;
    height: 25px;
  }
  .mt-20 {
    margin-top: 20px;
  }
  .flex-between {
    display: flex;
    justify-content: space-between;
  }
  .lh-32 {
    line-height: 32px;
  }
  .flex {
    display: flex;
    align-items: center;
    .el-icon {
      margin-left: 5px;
      cursor: pointer;
    }
  }
  .m-10 {
    margin: 10px 0;
  }
}
</style>
